﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using OpenTK;
using OpenTK.Graphics;
using OpenTK.Graphics.OpenGL;
using DDD;

namespace DevApp {
    public class Program2 : GameWindow {

        World wld;
        Graphics3D g3d;

        public Program2 ()
            : base (640, 480,
              new GraphicsMode (), "DDD: Textured Boxes", 0,
              DisplayDevice.Default, 3, 0,
              GraphicsContextFlags.ForwardCompatible | GraphicsContextFlags.Debug) {
        }

        protected override void OnLoad (System.EventArgs e) {

            //var img0 = new Image2D<byte> (DDD.PixelFormat.RGB, new System.Drawing.Bitmap ("Images/Barcelona.png"));
            //var img1 = new Image2D<byte> (DDD.PixelFormat.RGBA, new System.Drawing.Bitmap ("Images/Nadeko.png"));
            var img0 = ImageBuilder.Load<float> (DDD.PixelFormat.RGB8, new System.Drawing.Bitmap ("Images/Barcelona.png"));
            var img1 = ImageBuilder.Load<float> (DDD.PixelFormat.RGBA8, new System.Drawing.Bitmap ("Images/Nadeko.png"));
            var tex0 = new Sampler (SamplerType.Texture2D);
            var tex1 = new Sampler (SamplerType.Texture2D);
            tex0.SetImage (img0);
            tex1.SetImage (img1);

            var vert = new VertexShader ("Shaders/textured.vert");
            var frag = new FragmentShader ("Shaders/textured.frag");
            var shader = new ShaderProgram (vert, frag);

            var unifs = new UniformArray ();
            unifs.Add ("ModelViewMatrix", UniformArray.CurrentNode, () => ((Node)null).LocalToCamera);
            unifs.Add ("ProjectionMatrix", UniformArray.CurrentActiveCamera, () => ((Camera)null).ProjectionMatrix);
            unifs.Add ("Texture0", tex0);
            unifs.Add ("Texture1", tex1);

            var app = new Appearance ();
            app.SetShaderProgram (shader);
            app.AddUniformArray (unifs);
            app.AddSampler (tex0);
            app.AddSampler (tex1);

            var msh = MeshBuilder.CreateBox (2, 1, 2, "v_Position", null, "v_TexCoord");
            for (var f = 0; f < 6; f++) {
                msh.SetAppearance (f, app);
            }

            var mshNode = new Node ();
            mshNode.Attach (msh);
            mshNode.UserID = 100;

            var cam = new Camera ();
            cam.SetPerspective (45, Width / (float)Height, 0.1f, 100f);

            var camNode = new Node ();
            camNode.Attach (cam);
            camNode.SetTranslation (0, 0, 10);

            wld = new World ();
            wld.AddChild (mshNode);
            wld.AddChild (camNode);
            wld.SetActiveCamera (camNode);

            g3d = Graphics3D.GetInstance ();
            g3d.RenderPass += delegate {
                g3d.SetWorld (wld);
                g3d.SetClearColor (0, 0, 1, 1);
                g3d.SetClearDepth (1);
                g3d.SetColorClearEnabled (true);
                g3d.SetDepthClearEnabled (true);
                g3d.SetViewort (0, 0, Width, Height);
            };


            // 未実装
            VSync = VSyncMode.On;
            GL.Enable (EnableCap.DepthTest);
        }

        protected override void OnUnload (EventArgs e) {
            wld = null;
            GC.Collect ();
            g3d.Release ();
        }

        protected override void OnUpdateFrame (FrameEventArgs e) {
            
            var node = wld.Find (100) as Node;
            if (node != null) {
                node.Rotate (1, 0, 1, 0);
            }

        }

        protected override void OnRenderFrame (FrameEventArgs e) {

            g3d.Render ();

            SwapBuffers ();
        }

        /*
        [STAThread]
        public static void Main () {
            using (var example = new Program2 ()) {
                example.Run (30);
            }
        }
         */

    }
}
